﻿using Castle.Core.Logging;
using Inovout.Memberships;
using Inovout.Runtime;
using Inovout.Security;
using System;
using System.Diagnostics;
using System.Linq;
using System.Security.Principal;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;
using System.Web.Routing;

namespace Inovout.Web.Mvc
{
    [Authorize]
    public abstract class BaseController : Controller
    {
        internal IApplication Application
        {
            get;
            private set;
        }
        private Stopwatch stopwatch;
        public BaseController()
        {
            // todo:增加一个计时器
            //由于没有拿到ASP.NET MVC 4的源代码，不知为何重写Execute没用，需进一步验证。
            stopwatch = Stopwatch.StartNew();
            Application = ComponentRegistry.Resolve<IApplication>();
            ViewBag.Title = Application.Title ?? Application.Name;
        }
        protected bool TryGetApplicationSetting(string key, out string value)
        {
            value = null;
            if (Application.Settings.Contains(key))
            {
                value = Application.Settings[key].ToString();
                return true;
            }
            return false;
        }
        protected IMembershipUser MembershipUser
        {
            get;
            private set;
        }

        protected virtual IMembership Membership
        {
            get { return MembershipUser.Membership; }
        }
        protected virtual ISystemUser SystemUser
        {
            get { return MembershipUser.SystemUser; }
        }
        protected internal IExtendedLogger Logger
        {
            get;
            internal set;
        }

        protected override void Initialize(RequestContext requestContext)
        {
            base.Initialize(requestContext);
            Initialize();
        }
        protected virtual void Initialize()
        {
            if (Thread.CurrentPrincipal.Identity.IsAuthenticated)
            {
                MembershipUser = ComponentRegistry.Resolve<IMembershipUserService>().FindByClaimedIdentifier(Thread.CurrentPrincipal.Identity.Name);
                ViewBag.MembershipUser = MembershipUser;
                ViewBag.Membership = Membership;
            }
        }

        public virtual ActionResult Index()
        {
            return View();
        }

        protected override void OnAuthorization(AuthorizationContext filterContext)
        {
            var context = filterContext.HttpContext;
            IAuthenticationService authenticateService = ComponentRegistry.Resolve<IAuthenticationService>();
            if (context.User != null && context.User.Identity.IsAuthenticated)
            {
                var userPrincipal = authenticateService.GetCurrentUserPrincipal();

                if (userPrincipal == null)
                {
                    throw new Exception("userPrincipal == null.");
                    //  FormsAuthentication.SignOut();
                }
                else
                {
                    AuthenticateAs(context, userPrincipal);
                }
            }
            else
            {
                AuthenticateAs(context, UserPrincipal.AnonymousUserPrincipal);
            }
            base.OnAuthorization(filterContext);
        }

        private void AuthenticateAs(HttpContextBase context, IPrincipal user)
        {
            Thread.CurrentPrincipal = context.User = user;
        }

        protected internal XmlResult Xml(object data)
        {
            return Xml(data, null /* contentType */, null /* contentEncoding */);
        }

        protected internal XmlResult Xml(object data, string contentType)
        {
            return Xml(data, contentType, null /* contentEncoding */);
        }

        protected internal virtual XmlResult Xml(object data, string contentType, Encoding contentEncoding)
        {
            return new XmlResult
            {
                Data = data,
                ContentType = contentType,
                ContentEncoding = contentEncoding
            };
        }

        protected override ViewResult View(IView view, object model)
        {
            base.HttpContext.Request.Cookies.Remove(AntiForgeryConfig.CookieName);
            return base.View(view, model);
        }
        protected override ViewResult View(string viewName, string masterName, object model)
        {
            base.HttpContext.Request.Cookies.Remove(AntiForgeryConfig.CookieName);
            return base.View(viewName, masterName, model);
        }

        protected string GetParameterValue(string parameterName)
        {
            string parameterValue;
            TryGetParameterValue(parameterName, out parameterValue);
            return parameterValue;
        }
        protected bool TryGetParameterValue(string parameterName, out string parameterValue)
        {
            parameterValue = null;
            if (base.ControllerContext.RouteData.Values.ContainsKey(parameterName))
            {
                parameterValue = base.ControllerContext.RouteData.Values[parameterName].ToString();
            }
            else
            {
                if (base.Request.Headers.AllKeys.Contains(parameterName))
                {
                    parameterValue = base.Request.Headers.Get(parameterName);
                }
                else if (base.Request.QueryString.AllKeys.Contains(parameterName))
                {
                    parameterValue = base.Request.QueryString.Get(parameterName);
                }
            }
            return parameterValue != null;
        }

        [AllowAnonymous]
        public ActionResult Message(MessageType messageType, string message)
        {
            ViewBag.MessageType = messageType.ToString();
            ViewBag.Message = message;
            return View("Message");
        }
    }

}
